是一種用於在網絡上安全傳輸信息的開放標準。它通常用於身份驗證和授權方面的應用,尤其在Web應用程序和移動應用程序中廣泛使用。JWT的主要特點是它是一種緊湊的、自包含的數據格式,可以在各種系統之間輕鬆傳遞信息,同時確保數據的完整性和安全性。
以下是JWT的一些關鍵特點和組成部分:
JWT使用JSON(JavaScript Object Notation)作為其數據格式,這使得它易於理解和使用。
JWT包含了所有必要的信息,因此不需要在伺服器上存儲會話信息或狀態信息。這減輕了伺服器的負擔,並使應用程序可以更容易地擴展。
JWT可以使用數字簽名進行驗證,以確保其內容在傳輸過程中未被篡改。這有助於確保數據的完整性和安全性。
包含了有關令牌的元數據,例如使用的簽名算法(例如HS256或RS256)。
包含了令牌的主要信息,通常包括使用者ID、過期時間、發行者等等。
用於驗證令牌的簽名部分,確保令牌在傳輸過程中沒有被篡改。
延續上一篇
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
這裡將處理jwt相關作業,如:提取用戶,解析聲明與生成token等等
@Service
@Slf4j
public class JwtService {
// Token有效期限 (設定15分鐘過期)
private Long EXPIRATION_TIME = 60*60*1000; //單位ms
//BASE64編碼的密鑰
private String SECRET_KEY = "546A55A71347A254462D4......";
/**
* 從JWT令牌中提取用戶名
*/
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
/**
* 提取JWT令牌中的任何聲明(Claims),並通過提供的Function來解析它們。
*/
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
public String generateToken(UserDetails userDetails) {
return generateToken(new HashMap<>(), userDetails);
}
/**
* 簽發Token
*/
public String generateToken(
Map<String, Object> extractClaims,
UserDetails userDetails
) {
return Jwts
.builder()
.setClaims(extractClaims)
.setSubject(userDetails.getUsername()) //以Username做為Subject
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(getSignInKey(), SignatureAlgorithm.HS256)
.compact();
}
/**
* 驗證Token有效性,比對JWT和UserDetails的Username(Email)是否相同
* @return 有效為True,反之False
*/
public boolean isTokenValid(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername())) && !isTokenExpired(token);
}
/**
* 驗證token是否過期
*/
private boolean isTokenExpired(String token) {
final Date expirationDate = extractExpiration(token);
// return extractExpiration(token).before(new Date());
return expirationDate != null && expirationDate.before(new Date());
}
private Date extractExpiration(String token) {
return extractClaim(token, Claims::getExpiration);
}
/**
* 獲取令牌中所有的聲明將其解析
* @return 令牌中所有的聲明
*/
private Claims extractAllClaims(String token) {
return Jwts
.parserBuilder()
.setSigningKey(getSignInKey())
.build()
.parseClaimsJws(token)
.getBody();
}
/**
* 獲取JWT簽名的密鑰
*/
private Key getSignInKey() {
byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
return Keys.hmacShaKeyFor(keyBytes);
}
}
下一篇要介紹Jwt認證過濾器